package org.afox.util;

import java.util.*;

public class Variable
{
	private static final String defaultCategory = "default";
	private static HashMap categories = new HashMap();

	private HashMap variables = new HashMap();

	static
	{
		categories.put("default", new Variable());
	}

	private Variable()
	{
	}

	/** This method adds a variable of the specified name and value into the default variable category 
	 */
	public static Object put(String name, Object value)
	{
		if (name.indexOf("/") != (-1))
			return put(name.substring(0,name.indexOf("/")), name.substring(name.indexOf("/")+1), value);
		else
			return put(defaultCategory, name, value);
	}

	/** This method adds a variable of the specified name and value into the specified variable category 
	 */
	public static Object put(String category, String name, Object value)
	{
		Variable theVariable;
		if (categories.get(category)==null)
		{
			categories.put(category, new Variable());
		}
		return ((Variable)categories.get(category)).putImpl(name, value);
	}

	/** This method returns the value of the specified variable from the default variable category
	 */
	public static Object get(String name)
	{
		if (name.indexOf("/") != (-1))
			return get(name.substring(0,name.indexOf("/")), name.substring(name.indexOf("/")+1));
		else
			return get(defaultCategory, name);
	}

	/** This method returns the value of the specified variable from the specified variable category
	 */
	public static Object get(String category, String name)
	{
		try
		{
			return ((Variable)categories.get(category)).getImpl(name);
		}
		catch(Exception x)
		{
			throw new IllegalArgumentException("Category " + category + " not found.");
		}
	}

	/** This method returns the value of the specified variable from the specified variable category.  If variable or category
	    is not present, the default value is returned.
	 */
	public static Object get(String category, String name, String defaultValue)
	{
		try
		{
			Object returnValue = ((Variable)categories.get(category)).getImpl(name);
			if (returnValue == null)
				return defaultValue;
			else
				return returnValue;
		}
		catch(Exception x)
		{
			return defaultValue;
		}
	}

	/** This method removes a specified variable from the default category.  The removed object is returned.
	 */
	public static Object remove(String name)
	{
		if ((name == null) || name.length()==0)
			return null;

		if (name.indexOf("/") != (-1))
			return remove(name.substring(0,name.indexOf("/")), name.substring(name.indexOf("/")+1));
		else
			return remove(defaultCategory, name);
	}

	/** This method removes a specified variable from the specified category.  The removed object is returned.
	 */
	public static Object remove(String category, String name)
	{
		if ((name == null) || name.length()==0)
			return null;
		try
		{
			return ((Variable)categories.get(category)).removeImpl(name);
		}
		catch(Exception x)
		{
			throw new IllegalArgumentException("Category " + category + " not found.");
		}
	}

	public static List getCategories()
	{
		ArrayList returnList = new ArrayList();
		Iterator it = categories.keySet().iterator();
		while(it.hasNext())
		{
			returnList.add(it.next());
		}
		Collections.sort(returnList);
		return returnList;
	}

	public static Variable getVariables(String category)
	{
		return (Variable)categories.get(category);
	}

	private Object getImpl(String name)
	{
		return variables.get(name);
	}

	private Object putImpl(String name, Object value)
	{
		return variables.put(name, value);
	}

	private Object removeImpl(String name)
	{
		return variables.remove(name);
	}

	public Iterator keyIterator()
	{
		return variables.keySet().iterator();
	}

	public Map getMap()
	{
		return variables;
	}
	
	public int size()
	{
		return variables.size();
	}

}
